package com.dify.tool.common.utils;


import cn.hutool.json.JSONObject;
import com.dify.tool.common.constant.ErrorStatus;
import com.dify.tool.common.exception.BizException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HexFormat;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class DifyApiUtils {


    public static <T> String post(String url, String apiKey, T params) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            ObjectMapper mapper = new ObjectMapper();
            String jsonBody = mapper.writeValueAsString(params);
            HttpPost postHandle = new HttpPost(url);
            postHandle.setHeader("Authorization", "Bearer " + apiKey);
            postHandle.setHeader("Content-Type", "application/json");
            postHandle.setEntity(new StringEntity(jsonBody, "UTF-8"));
            try (CloseableHttpResponse uploadResponse = httpClient.execute(postHandle)) {
                String res = EntityUtils.toString(uploadResponse.getEntity());
                log.info("请求API成功，响应内容：{}", res);
                return res;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BizException(ErrorStatus.DIFY_API_FAIL);
        }
    }


    /**
     * 解析事件数据流
     */
    public static List<JSONObject> parseEvents(String eventData) {
        List<JSONObject> events = new ArrayList<>();
        String[] lines = eventData.split("\n");
        for (String line : lines) {
            if (line.startsWith("data: ")) {
                String jsonStr = line.substring(6).trim(); // 移除 "data: " 前缀
                if (!jsonStr.isEmpty()) {
                    events.add(new JSONObject(jsonStr));
                }
            }
        }
        return events;
    }

    /**
     * 解码 Unicode 转义序列
     */
    public static String decodeUnicode(String input) {
        // 使用正则表达式匹配 XXXX 格式的 Unicode 转义序列
        Pattern pattern = Pattern.compile("\\\\u([0-9a-fA-F]{4})");
        Matcher matcher = pattern.matcher(input);
        StringBuffer buffer = new StringBuffer();

        while (matcher.find()) {
            // 将十六进制字符串转换为字符
            char ch = (char) Integer.parseInt(matcher.group(1), 16);
            matcher.appendReplacement(buffer, String.valueOf(ch));
        }
        matcher.appendTail(buffer);

        return buffer.toString();
    }


    public static String getSignedFileUrl(String fileId, String fileExtension, String filesUrl, String secretKey) {

        //时间戳
        long timestamp = Instant.now().getEpochSecond();
        //16字节随机数
        String nonce = generateRandomHex(16);
        byte[] key = secretKey.getBytes(StandardCharsets.UTF_8);
        // 构造签名消息
        String message = String.format("file-preview|%s|%s|%s", fileId, timestamp, nonce);
        byte[] sign = null;
        try {
            sign = generateHmacSha256(key, message);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String encodedSign = Base64.getUrlEncoder().encodeToString(sign);
        // 构造完整URL
        return String.format("%s/files/tools/%s%s?timestamp=%s&nonce=%s&sign=%s", filesUrl, fileId, fileExtension, timestamp, nonce, encodedSign);
    }

    public static byte[] generateHmacSha256(byte[] key, String message) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKey = new SecretKeySpec(key, "HmacSHA256");
        hmac.init(secretKey);
        return hmac.doFinal(message.getBytes());
    }

    public static String generateRandomHex(int byteLength) {
        SecureRandom secureRandom = new SecureRandom();
        byte[] randomBytes = new byte[byteLength];
        secureRandom.nextBytes(randomBytes);
        return HexFormat.of().formatHex(randomBytes);
    }
}
